package com.es.interpreter;

import com.es.interpreter.config.IntepretConfig;
import com.es.interpreter.context.InterpretContext;
import com.es.interpreter.expression.AbstractExpression;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 解释操作，通过该类去获取解释器
 *
 * @author Will
 */
@Getter
@Setter
public class InterpretOperation implements Runnable {
    /**
     * 解释器
     */
    private AbstractExpression expression;
    /**
     * 解释上下文
     */
    private List<InterpretContext> contextList;

    /**
     * 新建JavaScript解释实现实例
     *
     * @param contextArr 解释上下文
     * @return 返回新创建实例
     */
    public static InterpretOperation newInstance2JavaScript(InterpretContext... contextArr) {
        InterpretOperation ins = new InterpretOperation();

        try {
            ins.init2JavaScript();
        } catch (Exception e) {
            throw new RuntimeException("InterpretOperation配置初始化失败", e);
        }

        if (contextArr == null || contextArr.length == 0) {
            ins.contextList = new ArrayList<>();
        } else {
            List<InterpretContext> rl = new ArrayList<>();
            Collections.addAll(rl, contextArr);
            ins.contextList = rl;
        }

        return ins;
    }

    @Override
    @SneakyThrows
    public void run() {
        if (this.expression == null) {
            throw new IllegalArgumentException("InterpretOperation解释属性为空，请检查！");
        }

        for (InterpretContext interpretContext : this.contextList) {
            this.expression.interpret(interpretContext);
        }
    }

    /**
     * 通过配置初始化为JavaScript解释实现
     */
    private void init2JavaScript() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String jsFlag = "javascriptFlag";
        IntepretConfig intepretConfig = IntepretConfig.getInstance().init2JavaScript();
        Map<String, Object> customParam = intepretConfig.getCustomParam();
        if (customParam == null || !customParam.containsKey(jsFlag)) {
            throw new NullPointerException("JavaScript引擎尚未初始化，请检查配置项中init2JavaScript！");
        }

        String javascriptExpressionClass = (String) customParam.get("javascriptExpressionClass");
        this.expression = (AbstractExpression) Class.forName(javascriptExpressionClass).newInstance();
    }
}
